package com.yc.litemonitoringserver.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * @program: lite_monitoring
 * @description: 服务器端架构:  主从reactor多工作线程模型
 * @author: zy
 * @create: 2025-03-20 06:27
 */
public final class LiteMonitoringServer {

    static final int PORT = 8083;

    private static final int MASTER_REACTOR_SIZE = 1;

    private static final int SLAVE_REACTOR_SIZE = Runtime.getRuntime().availableProcessors();
    private static final int BUSINESS_THREAD_SIZE = Runtime.getRuntime().availableProcessors() * 2;



    public static void main(String[] args) throws Exception {

        // 配置服务器
        //主reactor线程组(处理连接请求)
        EventLoopGroup masterReactorGroup = new NioEventLoopGroup(MASTER_REACTOR_SIZE);
        //从reactor线程组(处理IO请求)
        EventLoopGroup slaveReactorGroup = new NioEventLoopGroup(SLAVE_REACTOR_SIZE);
        // 业务线程组(处理业务逻辑)
         EventLoopGroup businessGroup = new NioEventLoopGroup(BUSINESS_THREAD_SIZE);

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(masterReactorGroup, slaveReactorGroup)  //****关键点:  主从reactor线程组
                    .channel(NioServerSocketChannel.class)
                    //主reactor配置项
                    .option(ChannelOption.SO_BACKLOG, 1024)    //联接队列的大小
                    .option(ChannelOption.SO_REUSEADDR, true)  //端口复用

                    //从reactor配置项
                    .childOption(ChannelOption.SO_KEEPALIVE, true)   //保持连接
                    .childOption(ChannelOption.TCP_NODELAY, true)    //关闭延迟发送

                    .handler(new LoggingHandler(LogLevel.INFO)) //通过handler配置日志处理器
                    .childHandler(new LiteMonitoringServerInitializer(  businessGroup   )); //通过childHandler配置业务处理器

            // 启动服务器
            ChannelFuture f = b.bind(PORT).sync();

            // 等待socket关闭
            f.channel().closeFuture().sync();
        } finally {
            // 关闭事件循环器终止线程
            masterReactorGroup.shutdownGracefully();
            slaveReactorGroup.shutdownGracefully();
            businessGroup.shutdownGracefully();
        }
    }
}
